package com.fjwt.gz.province.changchun.encrypt;

import com.alibaba.fastjson2.JSON;
import com.fjwt.gz.core.constants.ApiCodeEnum;
import com.fjwt.gz.core.model.ApiRes;
import net.logstash.logback.encoder.org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 验证签名
 */
public class SignVerifyFilter implements Filter {

    public static final String SECRET_KEY = "82E18EE52B687793";
    // 签名请求头
    public static final String SIGNATURE_HEADER = "auth-sign";

    //    public static final String TIMESTAMP_HEADER = "auth-timestamp";
    private static final Logger logger = LoggerFactory.getLogger(SignatureUtil.class);
    private static final String CUSTOMER_INFO_PATH1 = "/cyh/";
    private static final String CUSTOMER_INFO_PATH2 = "/prod-api/cyh/";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化操作
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        String uri = httpRequest.getRequestURI();

        logger.info("Handling request to URI: {}", uri);

        // 只对特定 API 接口进行签名验证
        if (uri.startsWith(CUSTOMER_INFO_PATH1) || uri.startsWith(CUSTOMER_INFO_PATH2)) {
//            System.out.println(httpRequest.getParameterMap());
//            HttpServletRequest wrappedRequest = new ContentCachingRequestWrapper(httpRequest);

//            Map<String, String[]> parameterMap = wrappedRequest.getParameterMap();
            Map<String, String[]> parameterMap = httpRequest.getParameterMap();

            Map<String, String> params = new HashMap<>();
            for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
                params.put(entry.getKey(), StringUtils.join(entry.getValue(), ","));
            }

            // 检查 Content-Type 是否为 JSON
            String contentType = httpRequest.getContentType();
            HttpServletRequest wrappedRequest = new ContentCachingRequestWrapper(httpRequest);
            if ("application/json".equalsIgnoreCase(contentType)) {

                // 读取请求体中的 JSON 数据
                BufferedReader reader = new BufferedReader(new InputStreamReader(wrappedRequest.getInputStream()));
                StringBuilder sb = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
                String requestBody = sb.toString();

                // 检查请求体是否为 JSON 数组
                if (StringUtils.isNotBlank(requestBody)) {
                    try {
                        List<String> listParam = JSON.parseArray(requestBody, String.class);
                        for (int i = 0; i < listParam.size(); i++) {
                            params.put("param" + (i + 1), listParam.get(i));
                        }
                    } catch (Exception e) {
                        logger.warn("Request body is not a valid JSON array for URI: {}", uri);
                        sendErrorResponse(httpResponse, HttpServletResponse.SC_BAD_REQUEST, "请求体不是有效的 JSON 数组");
                        return;
                    }
                }
            } else {
                // 处理 form-data 类型的请求
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    logger.info("Parameter: {} = {}", entry.getKey(), entry.getValue());
                }
            }

            logger.info("Received parameters: {}", params);

            // 从请求头获取签名
            String signature = httpRequest.getHeader(SIGNATURE_HEADER);
//            String timestamp = httpRequest.getHeader(TIMESTAMP_HEADER);

            if (signature == null) {
                logger.warn("Signature header not found for URI: {}", uri);
                sendErrorResponse(httpResponse, HttpServletResponse.SC_BAD_REQUEST, "缺少签名");
                return;
            }
            try {
                if (!SignatureUtil.verifySignature(params, SECRET_KEY, signature)) {
                    logger.warn("Signature verification failed for URI: {}", uri);
                    sendErrorResponse(httpResponse, HttpServletResponse.SC_FORBIDDEN, "签名验证失败");
                    return;
                }
            } catch (NoSuchAlgorithmException | InvalidKeyException e) {
                logger.error("Error occurred during signature verification: {}", e.getMessage(), e);
                sendErrorResponse(httpResponse, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "内部服务器错误");
                return;
            }
            chain.doFilter(wrappedRequest, response);
        } else {
            chain.doFilter(request, response);
        }


    }

    private void sendErrorResponse(HttpServletResponse response, int status, String message) throws IOException {
        response.setStatus(status);
        response.setContentType("application/json; charset=UTF-8");
        //response.getWriter().write(JSON.toJSONString(AjaxResult.error(status, message)));
        response.getWriter().write(JSON.toJSONString(ApiRes.fail(ApiCodeEnum.CUSTOM_FAIL, message)));
    }

    @Override
    public void destroy() {
        // 销毁操作
    }

    private static class ContentCachingRequestWrapper extends HttpServletRequestWrapper {
        private byte[] cachedBody;

        public ContentCachingRequestWrapper(HttpServletRequest request) throws IOException {
            super(request);
            cachedBody = readInputStream(request.getInputStream());
        }

        @Override
        public ServletInputStream getInputStream() throws IOException {
            final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(cachedBody);
            return new ServletInputStream() {
                @Override
                public boolean isFinished() {
                    return byteArrayInputStream.available() == 0;
                }

                @Override
                public boolean isReady() {
                    return true;
                }

                @Override
                public void setReadListener(ReadListener readListener) {
                    throw new UnsupportedOperationException();
                }

                @Override
                public int read() throws IOException {
                    return byteArrayInputStream.read();
                }
            };
        }

        @Override
        public BufferedReader getReader() throws IOException {
            return new BufferedReader(new InputStreamReader(getInputStream(), StandardCharsets.UTF_8));
        }

        private byte[] readInputStream(InputStream inputStream) throws IOException {
            byte[] buffer = new byte[1024];
            int bytesRead;
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            return bos.toByteArray();
        }
    }
}

